package com.bdqn.t350.ch11.config.shiro;

import com.bdqn.t350.ch11.bean.Right;
import com.bdqn.t350.ch11.bean.User;
import com.bdqn.t350.ch11.service.RightService;
import com.bdqn.t350.ch11.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import javax.annotation.Resource;
import java.util.List;


//@Configuration
public class MyShiroRealm extends AuthorizingRealm {
    @Resource
    UserService userService;

    @Resource
    RightService rightService;

    @Resource
    StringRedisTemplate stringRedisTemplate;

    //redis  中数据的 key  的前缀
    private String SHIRO_LOGIN_COUNT = "shiro_login_count_"; // 登录计数
    private String SHIRO_IS_LOCK = "shiro_is_lock_"; //锁定用户 锁定用户 登录

    /**
     * 认证
     *
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("进入自定义认证流程");

        //获取身份信息
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        //根据token获取用户名，需要去数据库里面查找是否有该用户名
        String username = token.getUsername();
        User user = userService.selectByName(username);

        ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
        //既然账号已经锁定那么就可用删除账号的登录次数
        if ("LOCK".equals(opsForValue.get(SHIRO_IS_LOCK + username))) {
            throw new DisabledAccountException("账号锁定");
        }

        //每次访问，登录次数+1
        opsForValue.increment(SHIRO_LOGIN_COUNT + username, 1);

        //设置账号锁定满足的条件
        if (Integer.parseInt(opsForValue.get(SHIRO_LOGIN_COUNT + username)) > 3) {
            //锁定账号
            opsForValue.set(SHIRO_IS_LOCK + username, "LOCK");
            stringRedisTemplate.delete(SHIRO_LOGIN_COUNT + username);
            throw new DisabledAccountException("账号锁定");
        }

        if (user == null) {
            throw new UnknownAccountException();
        }
        //根据用户名称获取该用户能访问的列表
        List<Right> rightList = rightService.getRightByUserName(user);
        user.setRightList(rightList);

        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(
                user,//身份(根据用户名去数据库查询出来的用户)
                user.getUsrPassword(),//密码，凭证
                ByteSource.Util.bytes("czkt"),
                getName());
        return info;
    }

    /**
     * 授权
     *
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("进入授权流程.....");

        //此时user里面应该要包含该用户能访问的资源
        User user = (User) principalCollection.getPrimaryPrincipal();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //给该用户授权能访问的资源
        //if(user.getUsrName().equals("czkt")){
        //info.addStringPermission("L05");
        //info.addStringPermission("L0503");
        //}
        List<String> list = userService.getByUserNameRightCode(user);
        for (String s : list) {
            info.addStringPermission(s);
        }
        return info;
    }
}
